package uebung04_h;

import java.awt.BorderLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

import Jama.EigenvalueDecomposition;
import Jama.Matrix;

import tools.ColorConversions;
import tools.Derivative;
import tools.Gauss;
import tools.Image;
import tools.ShowImage;

public class HarrisCorners02 {
	public static void main(String[] args) {
		try {
			
			final BufferedImage input = ImageIO.read(HarrisCorners02.class.getClassLoader().getResourceAsStream("res/checkerrot.png"));
			final int w = input.getWidth(), h = input.getHeight();
			
			int[] pixels = input.getRGB(0, 0, w, h, new int[w*h], 0, w);
			
			double[] lums = Image.getScalarLuminance(ColorConversions.getFastLuminance(pixels, new int[w*h]), new double[w*h]);
			
			double[] dxs = Derivative.dx(lums, w, h, new double[w*h]);
			double[] dys = Derivative.dy(lums, w, h, new double[w*h]);
			
			double[] as = new double[w*h], bs = new double[w*h];
			
			final int neighbours = 4;
			final double k = 0.02;
			
			Matrix sm = new Matrix(2,2);
			
			for (int y = neighbours; y<h-neighbours; y++) {
				for (int x = neighbours; x<w-neighbours; x++) {
					
					double xx = 0, yx = 0, yy = 0, sumW = 0;
					
					for (int j = -neighbours; j<neighbours; j++) {
						for (int i = -neighbours; i<neighbours; i++) {
							
							int index = x+i+(y+j)*w;
							
							double dx = dxs[index], dy = dys[index], weight = 1; // Gauss.gaussian1d(Math.sqrt(i*i+j*j), neighbours/3.);
							
							xx += dx*dx*weight;
							yx += dx*dy*weight;
							yy += dy*dy*weight;
							
							sumW += weight;
						}
					}
					
					xx /= sumW;
					yx /= sumW;
					yy /= sumW;
					
					sm.set(0, 0, xx);
					sm.set(0, 1, yx);
					sm.set(1, 0, yx);
					sm.set(1, 1, yy);
					
					double tr = sm.trace(), det = sm.det();
					
					double edgyness = det-k*tr*tr;
					
					as[x+y*w] = edgyness;
					bs[x+y*w] = -edgyness;
				}
			}
			/**
			double amax = Double.NEGATIVE_INFINITY, bmax = Double.NEGATIVE_INFINITY;
			
			for (int i = 0; i<as.length; i++) {
				if (Double.isNaN(as[i]))
					as[i] = 0;
				if (Double.isNaN(bs[i]))
					bs[i] = 0;
				amax = Math.max(as[i], amax);
				bmax = Math.max(bs[i], bmax);
			}
			
			System.out.println(amax+" "+bmax);

			bmax = Math.abs(bmax);
			
			for (int i = 0; i<as.length; i++) {
				
				as[i] = Math.max(as[i]/amax, 0);
				bs[i] = Math.max(bs[i]/bmax, 0);
			}

			amax = Double.NEGATIVE_INFINITY;
			bmax = Double.NEGATIVE_INFINITY;
			
			for (int i = 0; i<as.length; i++) {
				amax = Math.max(as[i], amax);
				bmax = Math.max(bs[i], bmax);
			}
			
			System.out.println(amax+" "+bmax);

			if (Double.compare(0, amax)!=0)
				for (int i = 0; i<as.length; i++) {
					as[i] /= amax;
				}
			**/
			
			int[] a = Image.prepare(as, new int[w*h]);
			int[] b = Image.prepare(bs, new int[w*h]);
//			a = Image.prepare(dxs, a);
			final BufferedImage output = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
			
//			pixels = Image.buildRGB(as, null, bs, pixels);
			pixels = Image.buildRGB(a, null, null, pixels);
			
			output.setRGB(0, 0, w, h, pixels, 0, w);

			JFrame ff = new JFrame();
			ff.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
			
			ff.add(new ShowImage(output), BorderLayout.CENTER);
			
			ff.pack();
			ff.setVisible(true);
		}
		catch (IOException iox) {
			iox.printStackTrace();
		}
	}
}
